#pragma region Copyright
/// <copyright>
/// Copyright (c) 2007 Ilia Shramko.
/// Released under the terms of the GNU General Public License.
/// </copyright>
#pragma endregion

#pragma once

namespace Utils
{
	class CMutexLock
	{
	public:
		CMutexLock(CMutex& mtx, bool bInitialLock = true) : m_mtx(mtx), m_bLocked(false)
		{
			if(bInitialLock)
				Lock();
		}
		
		~CMutexLock() throw()
		{
			if(m_bLocked)
				Unlock();
		}

		bool Lock(DWORD timeout = INFINITE)
		{
			ATLASSERT(!m_bLocked);

			DWORD dwResult;
			dwResult = ::WaitForSingleObject(m_mtx, timeout);
			if(dwResult == WAIT_ABANDONED)
			{
				ATLTRACE(atlTraceSync, 0, _T("Warning: abandoned mutex 0x%x\n"), (HANDLE)m_mtx);
			}
			m_bLocked = (dwResult == WAIT_OBJECT_0 || dwResult == WAIT_ABANDONED);
			return m_bLocked;
		}

		void Unlock() throw()
		{
			ATLASSERT(m_bLocked);
			m_mtx.Release();
			m_bLocked = false;
		}

		bool IsLocked() throw()
		{
			return m_bLocked;
		}

	// Implementation
	private:
		CMutex& m_mtx;
		bool m_bLocked;

		// Private to prevent accidental use
		CMutexLock(const CMutexLock&) throw();
		CMutexLock& operator=(const CMutexLock&) throw();
	};

//class CSyncObject
//{
//// Constructor
//public:
//	explicit CSyncObject(LPCTSTR /*pstrName*/)
//	{
//		m_hObject = NULL;
//	}
//
//	virtual ~CSyncObject()
//	{
//		if (m_hObject != NULL)
//		{
//			::CloseHandle(m_hObject);
//			m_hObject = NULL;
//		}
//	}
//
//// Attributes
//public:
//	operator HANDLE() const { return m_hObject; }
//	HANDLE  m_hObject;
//
//// Operations
//	virtual BOOL Lock(DWORD dwTimeout = INFINITE)
//	{
//		DWORD dwRet = ::WaitForSingleObject(m_hObject, dwTimeout);
//		if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_ABANDONED)
//			return TRUE;
//		else
//			return FALSE;
//	}
//
//	virtual BOOL Unlock() = 0;
//	
//	virtual BOOL Unlock(LONG /* lCount */, LPLONG /* lpPrevCount=NULL */)
//		{ return TRUE; }
//
//// Implementation
//public:
//	friend class CSingleLock;
//};
//
//
///////////////////////////////////////////////////////////////////////////////
//// CMutex
//
//class CMutex : public CSyncObject
//{
//// Constructor
//public:
//	/* explicit */ CMutex(BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL,
//		LPSECURITY_ATTRIBUTES lpsaAttribute = NULL) : CSyncObject(pstrName)
//	{
//		m_hObject = ::CreateMutex(lpsaAttribute, bInitiallyOwn, pstrName);
//	}
//
//// Implementation
//public:
//	virtual ~CMutex() {}
//
//	BOOL Unlock()
//	{
//		return ::ReleaseMutex(m_hObject);
//	}
//};

}